/*
* Copyright (c) 2007 by Kirill Kolodyazhniy.
* See the file "license.terms" for information on usage and redistribution.
*/

#include "dxmappings.h"

namespace Engine
{
	/*******************************************************************************/
	void DXMappings::Get(D3DPRESENT_PARAMETERS* d3dprams,const PresentParams& pp)
	{
		ZeroMemory(d3dprams,sizeof(D3DPRESENT_PARAMETERS));
		d3dprams->SwapEffect = D3DSWAPEFFECT_DISCARD;
		d3dprams->hDeviceWindow = 0;
		d3dprams->BackBufferCount = 1;
		d3dprams->EnableAutoDepthStencil = TRUE;

		d3dprams->AutoDepthStencilFormat = D3DFMT_D16;
		if(pp.zdepth > 16)
			d3dprams->AutoDepthStencilFormat = D3DFMT_D24S8;

		d3dprams->Windowed = !pp.fullscreen ? TRUE : FALSE;

		d3dprams->BackBufferFormat = D3DFMT_R5G6B5;
		if(pp.colordepth > 16)
			d3dprams->BackBufferFormat = D3DFMT_X8R8G8B8;

		d3dprams->BackBufferWidth = pp.width;
		d3dprams->BackBufferHeight = pp.height;
		d3dprams->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
	}
	/*******************************************************************************/
	D3DBLEND DXMappings::Get(SceneBlendFactor sbf)
	{
		switch( sbf )
		{
		case SBF_ONE:
			return D3DBLEND_ONE;
		case SBF_ZERO:
			return D3DBLEND_ZERO;
		case SBF_DEST_COLOUR:
			return D3DBLEND_DESTCOLOR;
		case SBF_SOURCE_COLOUR:
			return D3DBLEND_SRCCOLOR;
		case SBF_ONE_MINUS_DEST_COLOUR:
			return D3DBLEND_INVDESTCOLOR;
		case SBF_ONE_MINUS_SOURCE_COLOUR:
			return D3DBLEND_INVSRCCOLOR;
		case SBF_DEST_ALPHA:
			return D3DBLEND_DESTALPHA;
		case SBF_SOURCE_ALPHA:
			return D3DBLEND_SRCALPHA;
		case SBF_ONE_MINUS_DEST_ALPHA:
			return D3DBLEND_INVDESTALPHA;
		case SBF_ONE_MINUS_SOURCE_ALPHA:
			return D3DBLEND_INVSRCALPHA;
		}
		return D3DBLEND_FORCE_DWORD;
	}
	/*******************************************************************************/
	DWORD DXMappings::Get(CompareFunction cf)
	{
		switch( cf )
		{
			case CMPF_ALWAYS_FAIL:
				return D3DCMP_NEVER;
			case CMPF_ALWAYS_PASS:
				return D3DCMP_ALWAYS;
			case CMPF_LESS:
				return D3DCMP_LESS;
			case CMPF_LESS_EQUAL:
				return D3DCMP_LESSEQUAL;
			case CMPF_EQUAL:
				return D3DCMP_EQUAL;
			case CMPF_NOT_EQUAL:
				return D3DCMP_NOTEQUAL;
			case CMPF_GREATER_EQUAL:
				return D3DCMP_GREATEREQUAL;
			case CMPF_GREATER:
				return D3DCMP_GREATER;
		};
		return 0;
	}
	/*******************************************************************************/
	D3DFILLMODE DXMappings::Get(PolygonMode level)
	{
		switch(level)
		{
			case PM_POINTS:
				return D3DFILL_POINT;
			case PM_WIREFRAME:
				return D3DFILL_WIREFRAME;
			case PM_SOLID:
				return D3DFILL_SOLID;
		}
		return D3DFILL_FORCE_DWORD;
	}
	/*******************************************************************************/
	D3DDECLTYPE DXMappings::Get(VertexElementType vType)
	{
		switch (vType)
		{
		case VET_COLOR:
		case VET_COLOR_ABGR:
		case VET_COLOR_ARGB:
			return D3DDECLTYPE_D3DCOLOR;
			break;
		case VET_FLOAT1:
			return D3DDECLTYPE_FLOAT1;
			break;
		case VET_FLOAT2:
			return D3DDECLTYPE_FLOAT2;
			break;
		case VET_FLOAT3:
			return D3DDECLTYPE_FLOAT3;
			break;
		case VET_FLOAT4:
			return D3DDECLTYPE_FLOAT4;
			break;
        case VET_SHORT2:
			return D3DDECLTYPE_SHORT2;
			break;
        case VET_SHORT4:
			return D3DDECLTYPE_SHORT4;
			break;
        case VET_UBYTE4:
            return D3DDECLTYPE_UBYTE4;
            break;
		case VET_SHORT1:
		case VET_SHORT3:
			break;
		}
		return D3DDECLTYPE_FLOAT3;
	}
	/*******************************************************************************/
	D3DDECLUSAGE DXMappings::Get(VertexElementSemantic sem)
	{
		switch (sem)
		{
		case VES_BLEND_INDICES:
			return D3DDECLUSAGE_BLENDINDICES;
			break;
		case VES_BLEND_WEIGHTS:
			return D3DDECLUSAGE_BLENDWEIGHT;
			break;
		case VES_DIFFUSE:
			return D3DDECLUSAGE_COLOR; // NB index will differentiate
			break;
		case VES_SPECULAR:
			return D3DDECLUSAGE_COLOR; // NB index will differentiate
			break;
		case VES_NORMAL:
			return D3DDECLUSAGE_NORMAL;
			break;
		case VES_POSITION:
			return D3DDECLUSAGE_POSITION;
			break;
		case VES_TEXTURE_COORDINATES:
			return D3DDECLUSAGE_TEXCOORD;
			break;
		case VES_BINORMAL:
			return D3DDECLUSAGE_BINORMAL;
			break;
		case VES_TANGENT:
			return D3DDECLUSAGE_TANGENT;
			break;
		}
		return D3DDECLUSAGE_POSITION;
	}
	/*******************************************************************************/
	D3DFORMAT DXMappings::Get(IndexType type)
	{
		switch(type)
		{
		case INDEX_BUFFER_16:
			return D3DFMT_INDEX16;
		case INDEX_BUFFER_32:
			return D3DFMT_INDEX32;
		}
		return D3DFMT_INDEX16;
	}
	/*******************************************************************************/
	D3DSHADEMODE DXMappings::Get(ShadeMode val)
	{
		switch(val)
		{
		case SM_FLAT:
			return D3DSHADE_FLAT;
		case SM_GOURAUD:
			return D3DSHADE_GOURAUD;
		case SM_PHONG:
			return D3DSHADE_PHONG;
		}
		return D3DSHADE_FLAT;
	}
	/*******************************************************************************/
	D3DCULL DXMappings::Get(FaceCullMode val)
	{
		switch(val)
		{
		case FCM_NONE:
			return D3DCULL_NONE;
		case FCM_CW:
			return D3DCULL_CW;
		case FCM_CCW:
			return D3DCULL_CCW;
		}
		return D3DCULL_NONE;
	}
	/*******************************************************************************/
	D3DFOGMODE DXMappings::Get(FogMode fm)
	{
		switch( fm )
		{
		case FOG_EXP:
			return D3DFOG_EXP;
		case FOG_EXP2:
			return D3DFOG_EXP2;
		case FOG_LINEAR:
			return D3DFOG_LINEAR;
		case FOG_NONE:
			break;
		}
		return D3DFOG_FORCE_DWORD;
	}
	/*******************************************************************************/
	DWORD DXMappings::Get(StencilOperation op)
	{
		switch(op)
		{
		case SOP_KEEP:
			return D3DSTENCILOP_KEEP;
		case SOP_ZERO:
			return D3DSTENCILOP_ZERO;
		case SOP_REPLACE:
			return D3DSTENCILOP_REPLACE;
		case SOP_INCREMENT:
            return D3DSTENCILOP_INCRSAT;
		case SOP_DECREMENT:
            return D3DSTENCILOP_DECRSAT;
		case SOP_INCREMENT_WRAP:
            return D3DSTENCILOP_INCR;
		case SOP_DECREMENT_WRAP:
            return D3DSTENCILOP_DECR;
		case SOP_INVERT:
			return D3DSTENCILOP_INVERT;
		}
		return 0;
	}
	/*******************************************************************************/
	DWORD DXMappings::Get(TexCoordCalcMethod m, const D3DCAPS9& caps)
	{
		switch( m )
		{
		case TEXCALC_NONE:
			return D3DTSS_TCI_PASSTHRU;
		case TEXCALC_ENVIRONMENT_MAP_REFLECTION:
			return D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR;
		case TEXCALC_ENVIRONMENT_MAP_PLANAR:
			if (caps.VertexProcessingCaps & D3DVTXPCAPS_TEXGEN_SPHEREMAP)
			{
				// Use sphere map if available
				return D3DTSS_TCI_SPHEREMAP;
			}
			else
			{
				// If not, fall back on camera space reflection vector which isn't as good
                return D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR;
			}
		case TEXCALC_ENVIRONMENT_MAP_NORMAL:
			return D3DTSS_TCI_CAMERASPACENORMAL;
		case TEXCALC_ENVIRONMENT_MAP:
			if (caps.VertexProcessingCaps & D3DVTXPCAPS_TEXGEN_SPHEREMAP)
			{
				// Use sphere map if available
				return D3DTSS_TCI_SPHEREMAP;
			}
			else
			{
				// If not, fall back on camera space normal which isn't as good
				return D3DTSS_TCI_CAMERASPACENORMAL;
			}
        case TEXCALC_PROJECTIVE_TEXTURE:
            return D3DTSS_TCI_CAMERASPACEPOSITION;
		}
		return 0;
	}
	/*******************************************************************************/
	DWORD DXMappings::Get(TextureAddressingMode m, const D3DCAPS9& caps)
	{
		switch( m )
		{
		case TAM_WRAP:
			return D3DTADDRESS_WRAP;
		case TAM_MIRROR:
			return D3DTADDRESS_MIRROR;
		case TAM_CLAMP:
			return D3DTADDRESS_CLAMP;
        case TAM_BORDER:
            if (caps.TextureAddressCaps & D3DPTADDRESSCAPS_BORDER)
                return D3DTADDRESS_BORDER;
            else
                return D3DTADDRESS_CLAMP;
		}
		return D3DTADDRESS_FORCE_DWORD;
	}
	/*******************************************************************************/
	D3DSAMPLERSTATETYPE DXMappings::Get(FilterType ft)
    {
        switch (ft)
        {
        case FT_MIN:
            return D3DSAMP_MINFILTER;
            break;
        case FT_MAG:
            return D3DSAMP_MAGFILTER;
            break;
        case FT_MIP:
            return D3DSAMP_MIPFILTER;
            break;
        }

        // to keep compiler happy
        return D3DSAMP_MINFILTER;
    }
	/*******************************************************************************/
	DWORD DXMappings::Get(FilterOptions fo)
	{
        switch( fo )
        {
        case FO_ANISOTROPIC:
			return D3DTEXF_ANISOTROPIC;
        case FO_LINEAR:
			return D3DTEXF_LINEAR;
        case FO_POINT:
			return D3DTEXF_POINT;
        case FO_NONE:
			return D3DTEXF_NONE;
		}

        // should never get here
        return 0;
	}
	/*******************************************************************************/
	DWORD DXMappings::Get(LayerBlendOperationEx lbo, const D3DCAPS9& devCaps)
	{
		switch( lbo )
		{
		case LBX_SOURCE1:
			return D3DTOP_SELECTARG1;
		case LBX_SOURCE2:
			return D3DTOP_SELECTARG2;
		case LBX_MODULATE:
			return D3DTOP_MODULATE;
		case LBX_MODULATE_X2:
			return D3DTOP_MODULATE2X;
		case LBX_MODULATE_X4:
			return D3DTOP_MODULATE4X;
		case LBX_ADD:
			return D3DTOP_ADD;
		case LBX_ADD_SIGNED:
			return D3DTOP_ADDSIGNED;
		case LBX_ADD_SMOOTH:
			return D3DTOP_ADDSMOOTH;
		case LBX_SUBTRACT:
			return D3DTOP_SUBTRACT;
		case LBX_BLEND_DIFFUSE_ALPHA:
			return D3DTOP_BLENDDIFFUSEALPHA;
		case LBX_BLEND_TEXTURE_ALPHA:
			return D3DTOP_BLENDTEXTUREALPHA;
		case LBX_BLEND_CURRENT_ALPHA:
			return D3DTOP_BLENDCURRENTALPHA;
		case LBX_BLEND_MANUAL:
			return D3DTOP_BLENDFACTORALPHA;
		case LBX_DOTPRODUCT:
			if (devCaps.TextureOpCaps & D3DTEXOPCAPS_DOTPRODUCT3)
				return D3DTOP_DOTPRODUCT3;
			else
				return D3DTOP_MODULATE;
		case LBX_BLEND_DIFFUSE_COLOUR:
			if (devCaps.TextureOpCaps & D3DTEXOPCAPS_LERP)
				return D3DTOP_LERP;
			else
				return D3DTOP_MODULATE;
		}
		return 0;
	}
	/*******************************************************************************/
	DWORD DXMappings::Get(LayerBlendSource lbs)
	{
		switch( lbs )
		{
		case LBS_CURRENT:
			return D3DTA_CURRENT;
		case LBS_TEXTURE:
			return D3DTA_TEXTURE;
		case LBS_DIFFUSE:
			return D3DTA_DIFFUSE;
		case LBS_SPECULAR:
			return D3DTA_SPECULAR;
		case LBS_MANUAL:
			return D3DTA_TFACTOR;
		}
		return 0;
	}
	/*******************************************************************************/
	DWORD DXMappings::Get(TexCoordDim tcd)
	{
		switch(tcd)
		{
		case TCD_DISABLE:
			return D3DTTFF_DISABLE;
		case TCD_COUNT1:
			return D3DTTFF_COUNT1;
		case TCD_COUNT2:
			return D3DTTFF_COUNT2;
		case TCD_COUNT3:
			return D3DTTFF_COUNT3;
		case TCD_COUNT4:
			return D3DTTFF_COUNT4;
		case TCD_PROJECTED:
			return D3DTTFF_PROJECTED;
		}
		return 0;
	}
	/*******************************************************************************/
	D3DPRIMITIVETYPE DXMappings::Get(PrimitiveType type)
	{
		switch(type)
		{
		case PT_TRIANGLELIST:
			return D3DPT_TRIANGLELIST;
		case PT_POINTLIST:
			return D3DPT_POINTLIST;
		}
		return D3DPT_TRIANGLELIST;
	}
	/*******************************************************************************/
}
